
/*
 * sndpipe: A UNIX pipes-based audio stream processor toolkit.
 * Copyright (C) 2011  Bradley Worley
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to:
 *
 *   Free Software Foundation, Inc.
 *   51 Franklin Street, Fifth Floor
 *   Boston, MA  02110-1301, USA.
 */

/* include the sndpipe header. */
#include "sndpipe.h"

/* declare the function-specific help message strings. */
static struct function_help function_helps[] = {
 { SP_FUNC_GEN, "\n\
 * GEN: Generate waveforms.\n\
\n\
    -C,--channels CHANS\n\
    -r,--rate SRATE\n\
    -f,--format SFMT\n\
    -w,--wave {SIN,COS,TRI,SAW,SQR,PUL}\n\
    -F,--frequency FREQ\n\
    -A,--amplitude AMP\n\
   [-p,--phase PH]\n\
   [-o,--offset OFF]\n\
\n\
     Waveform generation digitally synthesizes various audio waveforms for\n\
     use in further analyses. Waveforms may be synthesized one-by-one if\n\
     CHANS is 1, or in groups of identical waves if CHANS is >1. The AMP,\n\
     PH and OFF fields expect values in [0,1].\n\
\n\
     If GEN is reading stream information from a preceding sndpipe instance,\n\
     the SRATE and SFMT are not required or read and the stream information\n\
     is passed through from the input. The parameters are required for new\n\
     instances, however.\n\
\n" },
 { SP_FUNC_CAP, "\n\
 * CAP: Capture from audio device.\n\
\n\
    -D,--device DEV\n\
    -C,--channels CHANS\n\
    -r,--rate SRATE\n\
    -f,--format SFMT\n\
\n\
     The capture function reads data from the sound card using calls to\n\
     the Advanced Linux Sound Architecture and adds the recorded data to\n\
     new channels in the audio stream.\n\
\n" },
 { SP_FUNC_OUT, "\n\
 * OUT: Output to audio device.\n\
\n" },
 { SP_FUNC_DEL, "\n\
 * DEL: Delete any given channel from the data stream.\n\
\n\
    -c,--channel CHAN\n\
\n\
     The delete function simply removes a selected channel from the output\n\
     audio data stream.\n\
\n" },
 { SP_FUNC_ADD, "\n\
 * ADD, SUB, MUL, DIV: Basic two-channel per-sample arithmetic.\n\
\n\
    -1,--channel-1 CH1\n\
    -2,--channel-2 CH2\n\
    -R,--remove\n\
\n\
     The math functions perform basic arithmetic on the piped audio data.\n\
     The original data may also be removed from the output stream, leaving\n\
     only the result of the arithmetic operation.\n\
\n" },
 { SP_FUNC_FIL, "\n\
 * FIL: Filter data using various time-domain methods.\n\
\n\
    -m,--mode MODE\n\
    -k,--coefficients COEFF\n\
    -C,--channels CHANS\n\
\n\
     The filter function performs simple time-domain filtering using various\n\
     finite impulse response filter coefficient sets, which may be formed\n\
     on the fly based on the number of coefficients desired. The MODE may\n\
     be one of any supported types:\n\
\n\
      SMA: Simple moving average\n\
      GAU: Sampled Gaussian filter\n\
      SG2: Savitzky-Golay quadratic filter\n\
      SG4: Savitzky-Golay quartic filter\n\
      EXT: Externally supplied coefficients\n\
\n\
     When MODE is EXT, the COEFF option is parsed as a list of custom filter\n\
     coefficients, separated by commas (without spaces), like so:\n\
\n\
      -m EXT -k 0.05,0.30,0.75,0.90,0.75,0.30,0.05\n\
\n\
     The CHANS parameter specifies which channels to filter.\n\
\n" },
 { SP_FUNC_BLK, "\n\
 * BLK: Break data into blocks.\n\
\n\
    -b,--buffer BUF\n\
    -T,--duration DUR\n\
\n\
     The block function prepends the stream with a new channel that contains\n\
     timebase information for later functions, such as 'WIN', 'FFT', and\n\
     'DIS'. The timebase can be generated according to a number of buffer\n\
     samples or a time span. If both options are given, the latter will be\n\
     used.\n\
\n" },
 { SP_FUNC_TRG, "\n\
 * TRG: Break data into blocks via automatic trigger.\n\
\n\
    -b,--buffer BUF\n\
    -T,--duration DUR\n\
    -c,--channel CHAN\n\
    -o,--offset OFF\n\
\n\
     The trigger function behaves in a similar manner, providing a simple\n\
     means of triggering on the positive-going edges of periodic signals,\n\
     with the possibility of including a minimum duration which the trigger\n\
     has to wait before re-checking for positive-going edges.\n\
\n\
     The offset value of the trigger function is valid between [-1:1] and\n\
     takes a default value of 0.2. When a positive-going edge is found that\n\
     exceeds this offset, the trigger fires, given the minimum wait duration\n\
     has passed.\n\
\n" },
 { SP_FUNC_WIN, "\n\
 * WIN: Multiply time-domain data by window function.\n\
\n\
    -m,--mode MODE\n\
    -C,--channels CHANS\n\
\n\
     The window function multiplies time-domain audio data by the specified\n\
     mathematical 'window' function. Several window functions are available\n\
     for use:\n\
\n\
      HAN: Hann function\n\
      HAM: Hamming 'raised cosine' function\n\
      TUK: Tukey 'tapered cosine' function\n\
      COS: Simple cosine function\n\
      LCZ: Lanczos resampling function\n\
      TRI: Bartlett 'triangular' function\n\
      GAU: Gaussian density function\n\
      BLK: Blackmann function\n\
\n\
     The CHANS parameter specifies which channels to apply the window to.\n\
\n" },
 { SP_FUNC_FFT, "\n\
 * FFT: Forward complex Fast Fourier Transform.\n\
\n" },
 { SP_FUNC_TXT, "\n\
 * TXT: Output audio data as text.\n\
\n\
     This function is totally self-explanatory. Every channel in the data\n\
     stream is output in a distinct column, where each column is separated\n\
     by spaces.\n\
\n" },
 { SP_FUNC_PAS, "\n\
 * PAS: Passthrough stream statistics.\n\
\n\
     This function passes the audio stream through without modifications,\n\
     but generates timing and throughput statistics on standard error.\n\
\n" },
 { SP_FUNC_DIS, "\n\
 * DIS: Graphically display audio data.\n\
\n" },
 { SP_UNKNOWN, SP_UNKNOWN }
};

/* failf_fn: prints a failure message and exits the application.
 * @f: the filename string of the calling source file.
 * @l: the line number in the calling source file.
 * @format: the printf-style format message to print.
 * @...: the printf-style arguments list, if any exist.
 *
 * the failf function prints a failure message to the standard error
 * file and promptly exits the application.
 */
void failf_fn (const int do_exit, const char *f, const unsigned int l,
               const char *format, ...) {
  /* declare required variables. */
  va_list vl;
  char *str;

  /* initialize the arguments list. */
  va_start (vl, format);

  /* allocate a fixed amount of memory for the output string. */
  str = (char *) malloc (sizeof (char) * 1024);
  vsnprintf (str, 1024, format, vl);

  /* output the newly allocated string to standard error. */
  fprintf (stderr, "sndpipe[%s]: %s:%u: %s!\n",
           opts_get_string (OPTS_S_FUNCTION),
           f, l, str);

  /* flush the output. */
  fflush (stderr);

  /* free the output string. */
  free (str);

  /* de-initialize the arguments list. */
  va_end (vl);

  /* exit the program with an error status. */
  if (do_exit)
    exit (SP_FAIL);
}

/* helpf: the function-specific help message function. :)
 * @func: the function to print specific help about.
 *
 * This function attempts to find specific help about a given functionality,
 * printing that help to stderr if it finds some.
 */
void helpf (const char *func) {
  /* declare required variables. */
  unsigned int i;

  /* loop through the array of function-specific help messages. */
  for (i = 0; function_helps[i].func != SP_UNKNOWN; i++) {
    /* see if this function matches ours. */
    if (strcmp (function_helps[i].func, func) == 0) {
      /* print the help message header. */
      fprintf (stderr, SP_HELP_HEADER);

      /* found it! print the help. */
      fprintf (stderr, "%s", function_helps[i].help);

      /* exit the function. */
      return;
    }
  }

  /* print the generic help message. */
  fprintf (stderr, SP_HELP_MESSAGE);
}

